home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / wgdb-42.lha / wgdb-4.2 / readline / vi_mode.c < prev   
C/C++ Source or Header  |  1992-09-11  |  16KB  |  926 lines

  1. /* vi_mode.c -- A vi emulation mode for Bash.
  2.  
  3.    Derived from code written by Jeff Sparkes (jeff1@????).
  4.  */
  5.  
  6.  
  7. /* **************************************************************** */
  8. /*                                    */
  9. /*            VI Emulation Mode                */
  10. /*                                    */
  11. /* **************************************************************** */
  12.  
  13. /* Last string searched for from `/' or `?'. */
  14. static char *vi_last_search = (char *)NULL;
  15. static int vi_histpos;
  16.  
  17. /* Non-zero means enter insertion mode. */
  18. int vi_doing_insert = 0;
  19.  
  20. /* *** UNCLEAN *** */
  21. /* Command keys which do movement for xxx_to commands. */
  22. static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
  23.  
  24. /* Keymap used for vi replace characters.  Created dynamically since
  25.    rarely used. */
  26. static Keymap vi_replace_map = (Keymap)NULL;
  27.  
  28. /* The number of characters inserted in the last replace operation. */
  29. static vi_replace_count = 0;
  30.  
  31. /* Yank the nth arg from the previous line into this line at point. */
  32. rl_vi_yank_arg (count)
  33.      int count;
  34. {
  35.   rl_yank_nth_arg (count, 0);
  36. }
  37.  
  38. /* Search again for the last thing searched for. */
  39. rl_vi_search_again (ignore, key)
  40.      int ignore, key;
  41. {
  42.   switch (key)
  43.     {
  44.     case 'n':
  45.       rl_vi_dosearch (vi_last_search, -1);
  46.       break;
  47.  
  48.     case 'N':
  49.       rl_vi_dosearch (vi_last_search, 1);
  50.       break;
  51.     }
  52. }
  53.  
  54. /* Do a vi style search. */
  55. rl_vi_search (count, key)
  56.      int count, key;
  57. {
  58.   int dir, c, save_pos;
  59.   char *p;
  60.  
  61.   switch (key)
  62.     {
  63.     case '?':
  64.       dir = 1;
  65.       break;
  66.  
  67.     case '/':
  68.       dir = -1;
  69.       break;
  70.  
  71.     default:
  72.       ding ();
  73.       return;
  74.     }
  75.  
  76.   vi_histpos = where_history ();
  77.   maybe_save_line ();
  78.   save_pos = rl_point;
  79.  
  80.   /* Reuse the line input buffer to read the search string. */
  81.   the_line[0] = 0;
  82.   rl_end = rl_point = 0;
  83.   p = (char *)alloca (2 + (rl_prompt ? strlen (rl_prompt) : 0));
  84.  
  85.   sprintf (p, "%s%c", rl_prompt ? rl_prompt : "", key);
  86.  
  87.   rl_message (p, 0, 0);
  88.  
  89.   while (c = rl_read_key ())
  90.     {
  91.       switch (c)
  92.     {
  93.     case CTRL('H'):
  94.     case RUBOUT:
  95.       if (rl_point == 0)
  96.         {
  97.           maybe_unsave_line ();
  98.           rl_clear_message ();
  99.           rl_point = save_pos;
  100.           return;
  101.         }
  102.  
  103.     case CTRL('W'):
  104.     case CTRL('U'):
  105.       rl_dispatch (c, keymap);
  106.       break;
  107.  
  108.     case ESC:
  109.     case RETURN:
  110.     case NEWLINE:
  111.       goto dosearch;
  112.       break;
  113.  
  114.     case CTRL('C'):
  115.       maybe_unsave_line ();
  116.       rl_clear_message ();
  117.       rl_point = 0;
  118.       ding ();
  119.       return;
  120.  
  121.     default:
  122.       rl_insert (1, c);
  123.       break;
  124.     }
  125.       rl_redisplay ();
  126.     }
  127.  dosearch:
  128.   if (vi_last_search)
  129.     free (vi_last_search);
  130.  
  131.   vi_last_search = savestring (the_line);
  132.   rl_vi_dosearch (the_line, dir);
  133. }
  134.  
  135. rl_vi_dosearch (string, dir)
  136.      char *string;
  137.      int dir;
  138. {
  139.   int old, save = vi_histpos;
  140.   HIST_ENTRY *h;
  141.  
  142.   if (string == 0 || *string == 0 || vi_histpos < 0)
  143.     {
  144.       ding ();
  145.       return;
  146.     }
  147.  
  148.   if ((save = history_search_pos (string, dir, vi_histpos + dir)) == -1)
  149.     {
  150.       maybe_unsave_line ();
  151.       rl_clear_message ();
  152.       rl_point = 0;
  153.       ding ();
  154.       return;
  155.     }
  156.  
  157.   vi_histpos = save;
  158.  
  159.   old = where_history ();
  160.   history_set_pos (vi_histpos);
  161.   h = current_history ();
  162.   history_set_pos (old);
  163.  
  164.   strcpy (the_line, h->line);
  165.   rl_undo_list = (UNDO_LIST *)h->data;
  166.   rl_end = strlen (the_line);
  167.   rl_point = 0;
  168.   rl_clear_message ();
  169. }
  170.  
  171. /* Completion, from vi's point of view. */
  172. rl_vi_complete (ignore, key)
  173.      int ignore, key;
  174. {
  175.   if (!whitespace (the_line[rl_point]))
  176.     {
  177.       if (!whitespace (the_line[rl_point + 1]))
  178.     rl_vi_end_word (1, 'E');
  179.       rl_point++;
  180.     }
  181.  
  182.   if (key == '*')
  183.     rl_complete_internal ('*');
  184.   else
  185.     rl_complete (0, key);
  186.  
  187.   rl_vi_insertion_mode ();
  188. }
  189.  
  190. /* Previous word in vi mode. */
  191. rl_vi_prev_word (count, key)
  192.      int count, key;
  193. {
  194.   if (count < 0)
  195.     {
  196.       rl_vi_next_word (-count, key);
  197.       return;
  198.     }
  199.  
  200.   if (uppercase_p (key))
  201.     rl_vi_bWord (count);
  202.   else
  203.     rl_vi_bword (count);
  204. }
  205.  
  206. /* Next word in vi mode. */
  207. rl_vi_next_word (count, key)
  208.      int count;
  209. {
  210.   if (count < 0)
  211.     {
  212.       rl_vi_prev_word (-count, key);
  213.       return;
  214.     }
  215.  
  216.   if (uppercase_p (key))
  217.     rl_vi_fWord (count);
  218.   else
  219.     rl_vi_fword (count);
  220. }
  221.  
  222. /* Move to the end of the ?next? word. */
  223. rl_vi_end_word (count, key)
  224.      int count, key;
  225. {
  226.   if (count < 0)
  227.     {
  228.       ding ();
  229.       return;
  230.     }
  231.  
  232.   if (uppercase_p (key))
  233.     rl_vi_eWord (count);
  234.   else
  235.     rl_vi_eword (count);
  236. }
  237.  
  238. /* Move forward a word the way that 'W' does. */
  239. rl_vi_fWord (count)
  240.      int count;
  241. {
  242.   while (count-- && rl_point < (rl_end - 1))
  243.     {
  244.       /* Skip until whitespace. */
  245.       while (!whitespace (the_line[rl_point]) && rl_point < rl_end)
  246.     rl_point++;
  247.  
  248.       /* Now skip whitespace. */
  249.       while (whitespace (the_line[rl_point]) && rl_point < rl_end)
  250.     rl_point++;
  251.     }
  252. }
  253.  
  254. rl_vi_bWord (count)
  255.      int count;
  256. {
  257.   while (count-- && rl_point > 0)
  258.     {
  259.       while (rl_point-- >= 0 && whitespace (the_line[rl_point]));
  260.       while (rl_point >= 0 && !whitespace (the_line[rl_point]))
  261.     rl_point--;
  262.       rl_point++;
  263.     }
  264. }
  265.  
  266. rl_vi_eWord (count)
  267.      int count;
  268. {
  269.   while (count -- && rl_point < (rl_end - 1))
  270.     {
  271.       while (rl_point++ < rl_end && whitespace (the_line[rl_point]));
  272.       while (rl_point++ < rl_end && !whitespace (the_line[rl_point]));
  273.       rl_point--;
  274.     }
  275. }
  276.  
  277. rl_vi_fword (count)
  278.      int count;
  279. {
  280.   while (count -- && rl_point < (rl_end - 1))
  281.     {
  282.       if (isident (the_line[rl_point]))
  283.     {
  284.       while (isident (the_line[rl_point]) && rl_point < rl_end)
  285.         rl_point += 1;
  286.     }
  287.       else if (!whitespace (the_line[rl_point]))
  288.     {
  289.       while (!isident (the_line[rl_point]) &&
  290.          !whitespace (the_line[rl_point]) && rl_point < rl_end)
  291.         rl_point += 1;
  292.     }
  293.  
  294.       while (whitespace (the_line[rl_point]) && rl_point < rl_end)
  295.     rl_point++;
  296.     }
  297. }
  298.  
  299. rl_vi_bword (count)
  300.      int count;
  301. {
  302.   while (count -- && rl_point > 0)
  303.     {
  304.       while (--rl_point > 0 && whitespace (the_line[rl_point]));
  305.       if (rl_point > 0)
  306.     {
  307.       if (isident (the_line[rl_point]))
  308.         while (--rl_point >= 0 && isident (the_line[rl_point]));
  309.       else
  310.         while (--rl_point >= 0 && !isident (the_line[rl_point]) &&
  311.            !whitespace (the_line[rl_point]));
  312.       rl_point++;
  313.     }
  314.     }
  315. }
  316.  
  317. rl_vi_eword (count)
  318.      int count;
  319. {
  320.   while (count -- && rl_point < rl_end - 1)
  321.     {
  322.       while (++rl_point < rl_end && whitespace (the_line[rl_point]));
  323.  
  324.       if (rl_point < rl_end)
  325.     {
  326.       if (isident (the_line[rl_point]))
  327.         while (++rl_point < rl_end && isident (the_line[rl_point]));
  328.       else
  329.         while (++rl_point < rl_end && !isident (the_line[rl_point])
  330.            && !whitespace (the_line[rl_point]));
  331.       rl_point--;
  332.     }
  333.     }
  334. }
  335.  
  336. rl_vi_insert_beg ()
  337. {
  338.   rl_beg_of_line ();
  339.   rl_vi_insertion_mode ();
  340.   return 0;
  341. }
  342.  
  343. rl_vi_append_mode ()
  344. {
  345.   if (rl_point < rl_end)
  346.     rl_point += 1;
  347.   rl_vi_insertion_mode ();
  348.   return 0;
  349. }
  350.  
  351. rl_vi_append_eol ()
  352. {
  353.   rl_end_of_line ();
  354.   rl_vi_append_mode ();
  355.   return 0;
  356. }
  357.  
  358. /* What to do in the case of C-d. */
  359. rl_vi_eof_maybe (count, c)
  360.      int count, c;
  361. {
  362.   rl_newline (1, '\n');
  363. }
  364.  
  365. /* Insertion mode stuff. */
  366.  
  367. /* Switching from one mode to the other really just involves
  368.    switching keymaps. */
  369. rl_vi_insertion_mode ()
  370. {
  371.   keymap = vi_insertion_keymap;
  372. }
  373.  
  374. rl_vi_movement_mode ()
  375. {
  376.   if (rl_point > 0)
  377.     rl_backward (1);
  378.  
  379.   keymap = vi_movement_keymap;
  380.   vi_done_inserting ();
  381. }
  382.  
  383. vi_done_inserting ()
  384. {
  385.   if (vi_doing_insert)
  386.     {
  387.       rl_end_undo_group ();
  388.       vi_doing_insert = 0;
  389.     }
  390. }
  391.  
  392. rl_vi_arg_digit (count, c)
  393.      int count, c;
  394. {
  395.   if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
  396.     rl_beg_of_line ();
  397.   else
  398.     rl_digit_argument (count, c);
  399. }
  400.  
  401. /* Doesn't take an arg count in vi */
  402. rl_vi_change_case (ignore1, ignore2)
  403.      int ignore1, ignore2;
  404. {
  405.   char c = 0;
  406.  
  407.   if (uppercase_p (the_line[rl_point]))
  408.     c = to_lower (the_line[rl_point]);
  409.   else if (lowercase_p (the_line[rl_point]))
  410.     c = to_upper (the_line[rl_point]);
  411.  
  412.   /* Vi is kind of strange here. */
  413.   if (c)
  414.     {
  415.       rl_begin_undo_group ();
  416.       rl_delete (1, c);
  417.       rl_insert (1, c);
  418.       rl_end_undo_group ();
  419.       rl_vi_check ();
  420.     }
  421.   else
  422.     rl_forward (1);
  423. }
  424.  
  425. rl_vi_put (count, key)
  426.      int count, key;
  427. {
  428.   if (!uppercase_p (key))
  429.     rl_forward (1);
  430.  
  431.   rl_yank ();
  432.   rl_backward (1);
  433. }
  434.  
  435. rl_vi_check ()
  436. {
  437.   if (rl_point && rl_point == rl_end)
  438.     rl_point--;
  439. }
  440.  
  441. rl_vi_column (count)
  442. {
  443.   if (count > rl_end)
  444.     rl_end_of_line ();
  445.   else
  446.     rl_point = count - 1;
  447. }
  448.  
  449. int
  450. rl_vi_domove (key, nextkey)
  451.      int key, *nextkey;
  452. {
  453.   int c, save;
  454.  
  455.   rl_mark = rl_point;
  456.   c = rl_read_key ();
  457.   *nextkey = c;
  458.  
  459.   if (!member (c, vi_motion))
  460.     {
  461.       if (digit (c))
  462.     {
  463.       save = rl_numeric_arg;
  464.       rl_digit_loop1 ();
  465.       rl_numeric_arg *= save;
  466.     }
  467.       else if ((key == 'd' && c == 'd') ||
  468.            (key == 'c' && c == 'c'))
  469.     {
  470.       rl_mark = rl_end;
  471.       rl_beg_of_line ();
  472.       return (0);
  473.     }
  474.       else
  475.     return (-1);
  476.     }
  477.  
  478.   rl_dispatch (c, keymap);
  479.  
  480.   /* No change in position means the command failed. */
  481.   if (rl_mark == rl_point)
  482.     return (-1);
  483.  
  484.   if ((c == 'w' || c == 'W') && rl_point < rl_end)
  485.     rl_point--;
  486.  
  487.   if (rl_mark < rl_point)
  488.     exchange (rl_point, rl_mark);
  489.  
  490.   return (0);
  491. }
  492.  
  493. /* A simplified loop for vi. Don't dispatch key at end.
  494.    Don't recognize minus sign? */
  495. rl_digit_loop1 ()
  496. {
  497.   int key, c;
  498.  
  499.   while (1)
  500.     {
  501.       rl_message ("(arg: %d) ", arg_sign * rl_numeric_arg, 0);
  502.       key = c = rl_read_key ();
  503.  
  504.       if (keymap[c].type == ISFUNC &&
  505.       keymap[c].function == rl_universal_argument)
  506.     {
  507.       rl_numeric_arg *= 4;
  508.       continue;
  509.     }
  510.       c = UNMETA (c);
  511.       if (numeric (c))
  512.     {
  513.       if (rl_explicit_arg)
  514.         rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
  515.       else
  516.         rl_numeric_arg = (c - '0');
  517.       rl_explicit_arg = 1;
  518.     }
  519.       else
  520.     {
  521.       rl_clear_message ();
  522.       rl_stuff_char (key);
  523.     }
  524.     }
  525. }
  526.  
  527. rl_vi_delete_to (count, key)
  528.      int count, key;
  529. {
  530.   int c;
  531.  
  532.   if (uppercase_p (key))
  533.     rl_stuff_char ('$');
  534.  
  535.   if (rl_vi_domove (key, &c))
  536.     {
  537.       ding ();
  538.       return;
  539.     }
  540.  
  541.   if ((c != '|') && (c != 'h') && rl_mark < rl_end)
  542.     rl_mark++;
  543.  
  544.   rl_kill_text (rl_point, rl_mark);
  545. }
  546.  
  547. rl_vi_change_to (count, key)
  548.      int count, key;
  549. {
  550.   int c;
  551.  
  552.   if (uppercase_p (key))
  553.     rl_stuff_char ('$');
  554.  
  555.   if (rl_vi_domove (key, &c))
  556.     {
  557.       ding ();
  558.       return;
  559.     }
  560.  
  561.   if ((c != '|') && (c != 'h') && rl_mark < rl_end)
  562.     rl_mark++;
  563.  
  564.   rl_begin_undo_group ();
  565.   vi_doing_insert = 1;
  566.   rl_kill_text (rl_point, rl_mark);
  567.   rl_vi_insertion_mode ();
  568. }
  569.  
  570. rl_vi_yank_to (count, key)
  571.      int count, key;
  572. {
  573.   int c, save = rl_point;
  574.  
  575.   if (uppercase_p (key))
  576.     rl_stuff_char ('$');
  577.  
  578.   if (rl_vi_domove (key, &c))
  579.     {
  580.       ding ();
  581.       return;
  582.     }
  583.  
  584.   rl_begin_undo_group ();
  585.   rl_kill_text (rl_point, rl_mark);
  586.   rl_end_undo_group ();
  587.   rl_do_undo ();
  588.   rl_point = save;
  589. }
  590.  
  591. rl_vi_delete (count)
  592. {
  593.   if (rl_point >= rl_end - 1)
  594.     {
  595.       rl_delete (count, 0);
  596.       if (rl_point > 0)
  597.     rl_backward (1);
  598.     }
  599.   else
  600.     rl_delete (count, 0);
  601. }
  602.  
  603. /* Turn the current line into a comment in shell history.  A ksh function */
  604. rl_vi_comment ()
  605. {
  606.   rl_beg_of_line ();
  607.   rl_insert_text (": ");    /* # doesn't work in interactive mode */
  608.   rl_redisplay ();
  609.   rl_newline (1, '\010');
  610. }
  611.  
  612. rl_vi_first_print ()
  613. {
  614.   rl_back_to_indent ();
  615. }
  616.  
  617. rl_back_to_indent (ignore1, ignore2)
  618.      int ignore1, ignore2;
  619. {
  620.   rl_beg_of_line ();
  621.   while (rl_point < rl_end && whitespace (the_line[rl_point]))
  622.     rl_point++;
  623. }
  624.  
  625. /* NOTE: it is necessary that opposite directions are inverses */
  626. #define    FTO     1        /* forward to */
  627. #define BTO    -1        /* backward to */
  628. #define FFIND     2        /* forward find */
  629. #define BFIND    -2        /* backward find */
  630.  
  631. rl_vi_char_search (count, key)
  632.      int count, key;
  633. {
  634.   static char target;
  635.   static int orig_dir, dir;
  636.   int pos;
  637.  
  638.   if (key == ';' || key == ',')
  639.     dir = (key == ';' ? orig_dir : -orig_dir);
  640.   else
  641.     {
  642.       target = rl_getc (in_stream);
  643.  
  644.       switch (key)
  645.     {
  646.     case 't':
  647.       orig_dir = dir = FTO;
  648.       break;
  649.  
  650.     case 'T':
  651.       orig_dir = dir = BTO;
  652.       break;
  653.  
  654.     case 'f':
  655.       orig_dir = dir = FFIND;
  656.       break;
  657.  
  658.     case 'F':
  659.       orig_dir = dir = BFIND;
  660.       break;
  661.     }
  662.     }
  663.  
  664.   pos = rl_point;
  665.  
  666.   if (dir < 0)
  667.     {
  668.       pos--;
  669.       do
  670.     {
  671.       if (the_line[pos] == target)
  672.         {
  673.           if (dir == BTO)
  674.         rl_point = pos + 1;
  675.           else
  676.         rl_point = pos;
  677.           return;
  678.         }
  679.     }
  680.       while (pos--);
  681.  
  682.       if (pos < 0)
  683.     {
  684.       ding ();
  685.       return;
  686.     }
  687.     }
  688.   else
  689.     {            /* dir > 0 */
  690.       pos++;
  691.       do
  692.     {
  693.       if (the_line[pos] == target)
  694.         {
  695.           if (dir == FTO)
  696.         rl_point = pos - 1;
  697.           else
  698.         rl_point = pos;
  699.           return;
  700.         }
  701.     }
  702.       while (++pos < rl_end);
  703.  
  704.       if (pos >= (rl_end - 1))
  705.     ding ();
  706.     }
  707. }
  708.  
  709. /* Match brackets */
  710. rl_vi_match ()
  711. {
  712.   int count = 1, brack, pos;
  713.  
  714.   pos = rl_point;
  715.   if ((brack = rl_vi_bracktype (the_line[rl_point])) == 0)
  716.     {
  717.       while ((brack = rl_vi_bracktype (the_line[rl_point])) == 0 &&
  718.          rl_point < rl_end - 1)
  719.     rl_forward (1);
  720.  
  721.       if (brack <= 0)
  722.     {
  723.       rl_point = pos;
  724.       ding ();
  725.       return;
  726.     }
  727.     }
  728.  
  729.   pos = rl_point;
  730.  
  731.   if (brack < 0)
  732.     {
  733.       while (count)
  734.     {
  735.       if (--pos >= 0)
  736.         {
  737.           int b = rl_vi_bracktype (the_line[pos]);
  738.           if (b == -brack)
  739.         count--;
  740.           else if (b == brack)
  741.         count++;
  742.         }
  743.       else
  744.         {
  745.           ding ();
  746.           return;
  747.         }
  748.     }
  749.     }
  750.   else
  751.     {            /* brack > 0 */
  752.       while (count)
  753.     {
  754.       if (++pos < rl_end)
  755.         {
  756.           int b = rl_vi_bracktype (the_line[pos]);
  757.           if (b == -brack)
  758.         count--;
  759.           else if (b == brack)
  760.         count++;
  761.         }
  762.       else
  763.         {
  764.           ding ();
  765.           return;
  766.         }
  767.     }
  768.     }
  769.   rl_point = pos;
  770. }
  771.  
  772. int
  773. rl_vi_bracktype (c)
  774.      int c;
  775. {
  776.   switch (c)
  777.     {
  778.     case '(': return  1;
  779.     case ')': return -1;
  780.     case '[': return  2;
  781.     case ']': return -2;
  782.     case '{': return  3;
  783.     case '}': return -3;
  784.     default:  return  0;
  785.     }
  786. }
  787.  
  788. rl_vi_change_char ()
  789. {
  790.   int c;
  791.  
  792.   c = rl_getc (in_stream);
  793.  
  794.   switch (c)
  795.     {
  796.     case '\033':
  797.     case CTRL('C'):
  798.       return;
  799.  
  800.     default:
  801.       rl_begin_undo_group ();
  802.       rl_delete (1, c);
  803.       rl_insert (1, c);
  804.       rl_end_undo_group ();
  805.       break;
  806.     }
  807. }
  808.  
  809. rl_vi_subst (count, key)
  810.      int count, key;
  811. {
  812.   rl_begin_undo_group ();
  813.   vi_doing_insert = 1;
  814.  
  815.   if (uppercase_p (key))
  816.     {
  817.       rl_beg_of_line ();
  818.       rl_kill_line (1);
  819.     }
  820.   else
  821.     rl_delete (1, key);
  822.  
  823.   rl_vi_insertion_mode ();
  824. }
  825.  
  826. rl_vi_overstrike (count, key)
  827.      int count, key;
  828. {
  829.   int i;
  830.  
  831.   if (vi_doing_insert == 0)
  832.     {
  833.       vi_doing_insert = 1;
  834.       rl_begin_undo_group ();
  835.     }
  836.  
  837.   for (i = 0; i < count; i++)
  838.     {
  839.       vi_replace_count++;
  840.       rl_begin_undo_group ();
  841.  
  842.       if (rl_point < rl_end)
  843.     {
  844.       rl_delete (1, key);
  845.       rl_insert (1, key);
  846.     }
  847.       else
  848.     rl_insert (1, key);
  849.  
  850.       rl_end_undo_group ();
  851.     }
  852. }
  853.  
  854. rl_vi_overstrike_delete (count)
  855.      int count;
  856. {
  857.   int i, s;
  858.  
  859.   for (i = 0; i < count; i++)
  860.     {
  861.       if (vi_replace_count == 0)
  862.     {
  863.       ding ();
  864.       break;
  865.     }
  866.       s = rl_point;
  867.  
  868.       if (rl_do_undo ())
  869.     vi_replace_count--;
  870.  
  871.       if (rl_point == s)
  872.     rl_backward (1);
  873.     }
  874.  
  875.   if (vi_replace_count == 0 && vi_doing_insert)
  876.     {
  877.       rl_end_undo_group ();
  878.       rl_do_undo ();
  879.       vi_doing_insert = 0;
  880.     }
  881. }
  882.  
  883. rl_vi_replace ()
  884. {
  885.   int i;
  886.  
  887.   vi_replace_count = 0;
  888.  
  889.   vi_replace_map = rl_make_bare_keymap ();
  890.  
  891.   for (i = ' '; i < 127; i++)
  892.     vi_replace_map[i].function = rl_vi_overstrike;
  893.  
  894.   vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
  895.   vi_replace_map[ESC].function = rl_vi_movement_mode;
  896.   vi_replace_map[RETURN].function = rl_newline;
  897.   vi_replace_map[NEWLINE].function = rl_newline;
  898.   keymap = vi_replace_map;
  899. }
  900.  
  901. /*
  902.  * Try to complete the word we are standing on or the word that ends with
  903.  * the previous character. A space matches everything.
  904.  * Word delimiters are space and ;.
  905.  */
  906. rl_vi_possible_completions()
  907. {
  908.   int save_pos = rl_point;
  909.  
  910.   if (!index (" ;", the_line[rl_point]))
  911.     {
  912.       while (!index(" ;", the_line[++rl_point]))
  913.     ;
  914.     }
  915.   else if (the_line[rl_point-1] == ';')
  916.     {
  917.       ding ();
  918.       return (0);
  919.     }
  920.  
  921.   rl_possible_completions ();
  922.   rl_point = save_pos;
  923.  
  924.   return (0);
  925. }
  926.